#genuary31
p5.js
#genuary31 #genuary2024
View Source Code
// Generative music / Generative audio / Generative sound.
// #genuary31
//
// by shibomb https://shibomb.xyz
// License: CC BY-NC-SA 4.0
//
// shibomb retains the copyright of the music created by this program and copy.
// The composer of these songs is shibomb.
//
let objs = [];
const START_DELAY = 1000;
let BPM = 32;
const MINUTE = 60 * 1000; // 60sec. 1000millis
const BEAT = 16;
let term = 0;
let count = 0;
let click = 0;
let measure = 0;
let step = 4;
let beatPerStep = -1;
let oldBeatPerStep = -2;
let beatPerBEAT = -1;
let oldBeatPerBEAT = -2;
function updateBeat() {
// BPM beat per minute
const ml = millis() - START_DELAY;
term = MINUTE / ((BPM * BEAT) / 4);
count = int(ml / term);
click = int(count / (BEAT / 4));
measure = int(click / step);
beatPerStep = int(click % step);
beatPerBEAT = int(count % BEAT);
}
function storeOldBeat() {
oldBeatPerStep = beatPerStep;
oldBeatPerBEAT = beatPerBEAT;
}
let W, H;
function setup() {
W = windowWidth;
H = windowHeight;
createCanvas(W, H);
initObjs();
setInterval(initObjs, 6 * 60 * 1000)
}
function mouseClicked() {
initObjs();
}
let oldBeatPerStepFrameCount = -1;
let oldBeatPerBEATFrameCount = -1;
function draw() {
userStartAudio();
background(0);
if (millis() < START_DELAY) return;
updateBeat();
// debug
const ml = millis() - START_DELAY;
const sec = int(ml / 1000);
fill(255);
text(`time: ${int(sec / 60)}:${sec}, BPM: ${BPM} `, 10, 20);
text(
`measure :${measure + 1}, click: ${click + 1}, count: ${count}`,
10,
40
);
text(`${beatPerStep + 1} / ${step}, ${beatPerBEAT + 1} /${BEAT}`, 10, 60);
if (oldBeatPerStep != beatPerStep) {
oldBeatPerStepFrameCount = frameCount;
}
if (oldBeatPerBEAT != beatPerBEAT) {
oldBeatPerBEATFrameCount = frameCount;
}
if (frameCount < oldBeatPerStepFrameCount + 8) {
if (beatPerStep == 0) {
noStroke();
fill(255);
circle(W - 120, 40, 40);
}
noStroke();
fill(255, 128);
circle(W - 80, 40, 40);
}
if (frameCount < oldBeatPerBEATFrameCount + 2) {
noStroke();
fill(255, 64);
circle(W - 40, 40, 40);
}
fill(255);
text(`click to generate next.`, 10, H - 40);
text(`(c) shibomb.`, W - 100, H - 20);
// --------------------------------------------------
// play
for (const obj of objs) {
obj.update();
}
for (const obj of objs) {
obj.play();
}
// next
storeOldBeat();
}
function initObjs() {
for (const obj of objs) {
obj.destory();
}
objs = [];
BPM = random([32, 48, 64, 70, 90, 110, 120, 180, 320, 1024]);
term = MINUTE / ((BPM * BEAT) / 4);
for (let i = 0; i < 2; i++) {
objs.push(
new MySound(
{
noise: {
type: random(["white", "pink", "brown"]),
amp: 0,
},
env: {
adsr: {
a: random(0.0005, 0.002),
d: random(0.06, 0.1),
s: random(0.08, 0.1),
r: random(0.05, 0.1),
},
range: {
a: 0.1,
r: 0,
},
},
},
randomBeat()
)
);
}
//
if (random() < 0.5) {
let beats = randomBeat(8, random(0.125, 0.8));
let beatsNotes = randomBeatsNotes(beats, 1, ["4", "5", "6"]);
objs.push(
new MySynth(
{
dur: (term / 1000) * 4,
delay: random([0]),
vel: 0.2,
},
beats,
beatsNotes
)
);
}
//
objs.push(
new MySynth(
{
dur: (term / 1000) * 8,
delay: random([0, term / 1000]),
vel: 0.2,
},
[
[0],
[0],
[0],
[0],
[0],
[0],
[0],
[0, 8],
[0],
[0],
[0],
[0],
[0],
[0],
[0],
[0, 8],
],
[
[randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes(), randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes()],
[randomNotes(), randomNotes()],
]
)
);
objs.push(
new MySynth(
{
dur: (term / 1000) * 8,
delay: 0,
vel: 0.6,
},
[
[0],
[0],
[0],
[0],
[0],
[0],
[0],
[0, 8],
[0],
[0],
[0],
[0],
[0],
[0],
[0],
[0, 8],
],
[
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"]), randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"])],
[randomNotes(1, ["2", "3"]), randomNotes(1, ["2", "3"])],
]
)
);
console.log(`BPM:${BPM}`);
for (const obj of objs) {
console.log(`obj`, obj.toString());
}
}
function randomBeat(mMax = 4, randBoarder = 0.25) {
let ret = [];
for (let m = 0; m < mMax; m++) {
ret.push([]);
for (let i = 0; i < 32; i++) {
if (random() < randBoarder) {
ret[m].push(i);
}
}
}
return ret;
}
function randomBeatsNotes(beats, mMax = 4, oList = ["4", "5"]) {
let ret = [];
for (let i = 0; i < beats.length; i++) {
ret.push([]);
const beat = beats[i];
for (let j = 0; j < beat.length; j++) {
ret[i].push(randomNotes(mMax, oList));
}
}
return ret;
}
function randomNotes(mMax = 4, oList = ["4", "5"]) {
let ret = [];
for (let m = 0; m < mMax; m++) {
ret.push(randomNote(oList));
}
return ret;
}
function randomNote(oList) {
ret =
random(["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]) +
// random(["A", "B", "C", "D", "E", "F", "G"]) +
random(oList);
return ret;
}
// function initObjs_test() {
// BPM = 32;
// objs.push(
// new MySound(
// {
// noise: {
// type: "white",
// amp: 0,
// },
// env: {
// adsr: {
// a: 0.001,
// d: 0.11,
// s: 0.2,
// r: 0.1,
// },
// range: {
// a: 1,
// r: 0,
// },
// },
// },
// [[8], [8]]
// ),
// new MySound(
// {
// noise: {
// type: "brown",
// amp: 0,
// },
// env: {
// adsr: {
// a: 0.001,
// d: 0.1,
// s: 0.2,
// r: 0.1,
// },
// range: {
// a: 1,
// r: 0,
// },
// },
// },
// [[0, 4, 8, 12]]
// ),
// new MySynth(
// {
// dur: (term / 1000) * 8,
// delay: term / 1000,
// vel: 0.2
// },
// [[0], [0], [0], [0], [0], [0], [0], [0, 8]],
// [
// // AM7→Dm7→G7sus→CM7→FM7→Bm7→D/E→A→Dm
// [["A4", "C#4", "E4", "G#4"]],
// [["D4", "F4", "A5", "C5"]],
// [["G4", "C5", "D5", "F5"]],
// [["C4", "E4", "G4", "B5"]],
// [["F4", "A5", "C5", "E5"]],
// [["B4", "D4", "F#4", "A5"]],
// [["E4", "D4", "F#4", "A5"]],
// [
// ["A4", "C#4", "E4", "E4"],
// ["D4", "F4", "A5", "A5"],
// ],
// ]
// )
// );
// }
class MySound {
// {
// noise: {
// type: "white",
// amp: 0,
// },
// env: {
// adsr: {
// a: 0.001,
// d: 0.11,
// s: 0.2,
// r: 0.1,
// },
// range: {
// a: 1,
// r: 0,
// },
// },
// };
constructor(params, playAt) {
this.params = params;
this.playAt = playAt;
this.init();
}
toString() {
return JSON.stringify(
{ class: "MySound", params: this.params, playAt: this.playAt },
"\n",
2
);
}
init() {
this.noise = new p5.Noise(this.params.noise.type);
this.noise.start();
// multiply noise volume by 0
// (keep it quiet until we're ready to make noise!)
this.noise.amp(this.params.noise.amp);
this.env = new p5.Env(0,0,0,0.0);
// set attackTime, decayTime, sustainRatio, releaseTime
this.env.setADSR(
this.params.env.adsr.a,
this.params.env.adsr.d,
this.params.env.adsr.s,
this.params.env.adsr.r
);
// set attackLevel, releaseLevel
// console.log("atadas", this.params.env.range.a)
this.env.setRange(this.params.env.range.a, this.params.env.range.r);
}
destory() {
this.noise.disconnect();
}
update() {}
play() {
if (oldBeatPerBEAT != beatPerBEAT) {
const playMeasureIndex = measure % this.playAt.length;
if (this.playAt[playMeasureIndex].includes(beatPerBEAT)) {
this.env.play(this.noise);
this.display();
}
}
}
display() {
stroke(255);
const y = random(H)
line(random(W), y, random(W), y);
}
}
class MySynth {
constructor(params, playAt, notes) {
this.params = params;
this.playAt = playAt;
this.notes = notes;
this.init();
}
toString() {
return JSON.stringify(
{
class: "MySynth",
params: this.params,
playAt: this.playAt,
notes: this.notes,
},
null,
2
);
}
init() {
this.polySynth = new p5.PolySynth(p5.MonoSynth, 32);
}
destory() {
this.polySynth.disconnect();
this.polySynth.dispose();
}
update() {}
play() {
if (oldBeatPerBEAT != beatPerBEAT) {
const playMeasureIndex = measure % this.playAt.length;
if (this.playAt[playMeasureIndex].includes(beatPerBEAT)) {
let dur = this.params.dur;
let time = 0;
let vel = this.params.vel;
const idx = this.playAt[playMeasureIndex].indexOf(beatPerBEAT);
const notes = this.notes[playMeasureIndex][idx];
time = 0;
for (const note of notes) {
this.polySynth.play(note, vel, (time += this.params.delay), dur);
// this.polySynth.play(note, vel, 0, 0.1);
this.display();
}
}
}
}
display() {
stroke(255);
const x = random(W)
line(x, random(H), x, random(H));
}
}